package com.qdsgjsfk.vision.socket;

import android.content.Context;
import android.net.wifi.WifiManager;
import android.util.Log;

import com.qdsgjsfk.vision.eventbus.BlueTooth;
import com.qdsgjsfk.vision.eventbus.Err;
import com.qdsgjsfk.vision.model.Msg;
import com.qdsgjsfk.vision.util.Constant;

import org.greenrobot.eventbus.EventBus;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.lang.reflect.Method;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import jz.joyoung.robot.util.LogUtil;

/**
 * @Description: socket
 * @Author: lzp
 * @CreateDate: 2021/10/14 15:46
 * @UpdateRemark: 更新说明
 */
public class SocketServer {
    private DatagramSocket socket;
    private DatagramPacket receivePacket;
    private byte[] data = new byte[2048];
    private ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
    private boolean isThreadRunning = false;
    private Thread receiveThread;
    private Context mContext;

    private String tempData = "";
    private String tempDataOne = "";

    public SocketServer(Context context) {
        this.mContext = context;
    }

    /**
     * @steps listen();
     * @effect socket监听数据
     */
    public void beginListen() {
        if (socket != null) return;
        try {
            //在7778端口上监听数据
            socket = new DatagramSocket(7778);
            if (receivePacket == null) {
                // 创建接受数据的 packet
                receivePacket = new DatagramPacket(data, data.length);
            }
            receiveThread = new Thread(() -> {
                LogUtil.e("ReceiveThread is running..." + Thread.currentThread().getName());
                receiveMessage();
            });
            isThreadRunning = true;
            receiveThread.start();
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }


    /**
     * 处理接受到的消息
     */
    private void receiveMessage() {
        while (isThreadRunning) {
            if (socket != null) {
                try {
                    socket.receive(receivePacket);
                } catch (IOException e) {
                    close();
                    e.printStackTrace();
                    return;
                }
            }
            if (receivePacket == null || receivePacket.getLength() == 0) {
                continue;
            }
            // 准备接收数据
//            LogUtil.e("IPAddress---" + inetAddress);
            tempData = tempData + " " + new String( receivePacket.getData() ).substring( 0, receivePacket.getLength() );
            tempDataOne = new String( receivePacket.getData(), receivePacket.getOffset(), receivePacket.getLength() );
            LogUtil.e( "接收的数据tempData1---", Thread.currentThread().getName() + "---" + tempDataOne + " from " + receivePacket.getAddress().getHostAddress() + ":" + receivePacket.getPort() );
            //{"code":2,"size":7,"value":"90","chartType":0} size=7 表示4.7那一行
            //{"code":3,"size":0,"value":"180","chartType":0}
            if (getJSONType( tempDataOne )) {
                try {
                    JSONObject object = new JSONObject( tempDataOne );
                    int code = object.getInt( "code" );
                    String value = object.getString( "value" );
                    if (code == 100) { //代表连接设备成功
                        EventBus.getDefault().postSticky( new BlueTooth( value, Constant.CODE_WS_SUCCESS ) );
                        tempDataOne = "";
                    } else {
                        EventBus.getDefault().postSticky( new Msg( tempDataOne ) );
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                try {
                    JSONObject object = new JSONObject(tempDataOne);
                    EventBus.getDefault().postSticky(new BlueTooth(tempDataOne, 110));
                    tempDataOne = "";
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            } else {
                if (tempData.trim().endsWith("E")) {
                    EventBus.getDefault().postSticky(new BlueTooth(tempData, 1));
                    tempData = "";
                } else if (tempData.trim().endsWith("End")) {
                    EventBus.getDefault().postSticky(new BlueTooth(tempData, 2));
                    tempData = "";
                } else {
                    EventBus.getDefault().postSticky(new BlueTooth(tempData.trim(), 3));
                    tempData = "";
                }
            }
            // 每次接收完UDP数据后，重置长度。否则可能会导致下次收到数据包被截断。
            if (receivePacket != null) {
                receivePacket.setLength(2048);
            }
        }
    }

    /**
     * 发送消息
     *
     * @param msg  消息
     * @param site ip地址
     * @param port 端口号
     */
    public void sendMessage(String msg, String site, int port) {
        singleThreadExecutor.execute( () -> {
            if (!socket.isClosed()) {
                try {
                    String[] ipStr = site.split( "\\." );
                    byte[] ipBuf = new byte[4];
                    for (int i = 0; i < 4; i++) {
                        ipBuf[i] = (byte) (Integer.parseInt( ipStr[i] ) & 0xff);
                    }
                    InetAddress inetAddress = InetAddress.getByAddress( ipBuf );
                    byte[] data = msg.getBytes();
                    DatagramPacket sendPacket = new DatagramPacket( data, data.length, inetAddress, port );
                    socket.send( sendPacket );
                    LogUtil.e( "发送的数据---", new String( sendPacket.getData() ) + " to " + sendPacket.getAddress().getHostAddress() + ":" + sendPacket.getPort() );
                } catch (IOException e) {
                    e.printStackTrace();
                    EventBus.getDefault().postSticky(new Err("视力表未连接"));
                }
            } else {
                EventBus.getDefault().postSticky(new Err("视力表未连接"));
            }
        });
    }

    public void close() {
        isThreadRunning = false;
        receivePacket = null;
        if (receiveThread != null) {
            receiveThread = null;
        }
        if (socket != null) {
            socket.close();
            socket = null;
        }
    }

    private String getLocalIpAddress() {
        if (getWifiApState(mContext) == 13) {
            return "192.168.43.1";
        } else {
            try {
                String ipv4;
                ArrayList<NetworkInterface> nilist = Collections.list(NetworkInterface.getNetworkInterfaces());
                for (NetworkInterface ni : nilist) {
                    ArrayList<InetAddress> ialist = Collections.list(ni.getInetAddresses());
                    for (InetAddress address : ialist) {
                        if (!address.isLoopbackAddress() && address instanceof Inet4Address) {
                            ipv4 = address.getHostAddress();
                            return ipv4;
                        }
                    }
                }

            } catch (SocketException ex) {
                Log.e("localip", ex.toString());
            }
        }
        return null;
    }

    private int getWifiApState(Context mContext) {
        WifiManager wifiManager = (WifiManager) mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        try {
            assert wifiManager != null;
            Method method = wifiManager.getClass().getMethod("getWifiApState");
            return (int) (Integer) method.invoke(wifiManager);
        } catch (Exception e) {
            return -1;
        }
    }

    private boolean getJSONType(String str) {
        str = str.trim();
        if (str.startsWith("{") && str.endsWith("}")) {
            return true;
        } else return str.startsWith("[") && str.endsWith("]");
    }
}